package com.bearingnavi.android.util;

import java.util.Iterator;

import org.apache.log4j.Logger;

import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Point;
import com.bearingnavi.android.R;
import com.bearingnavi.android.dialogs.AboutDialog;
import com.bearingnavi.android.dialogs.CleanDialog;
import com.bearingnavi.android.dialogs.Dialog;
import com.bearingnavi.android.dialogs.LongpressDialog;
import com.bearingnavi.android.dialogs.NewBearingDialog;
import com.bearingnavi.android.dialogs.SettingsDialog;
import com.bearingnavi.android.overlays.BearingOverlay;
import com.bearingnavi.android.overlays.WalkingPathOverlay;
import com.bearingnavi.android.overlays.WayPointOverlay;
import com.bearingnavi.android.services.LocationService;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;

public class OverlayUtil {
	
	private static Logger log = Logger.getLogger(OverlayUtil.class);
	
	public static void drawBearingLine(final MapView mapView, final Context context,
			final LocationService locationService, boolean longpress, GeoPoint geoPoint) {
		
		
		try {
			if (longpress == false)
			{
				if (locationService.getLastGeoPoint() == null) {
					
					Dialog.buildAlertDialog(context, "Error !", "Please wait for GPS signal first.");
					
					return;
				}
			}
			
			NewBearingDialog dialog = new NewBearingDialog(context, new NewBearingDialog.ConfirmBearingHandler() {
				
				public void onConfirm(int bearing, int distance, GeoPoint fromPoint, int wayPoint) {					
					
					if (fromPoint == null) {
						fromPoint = locationService.getLastGeoPoint();
					}
					
					if (wayPoint != 0) {
						boolean wpFound = false;
						Iterator<Overlay> iterator = mapView.getOverlays().iterator();
						
						while (iterator.hasNext()) {
							
							Overlay overlay = (Overlay) iterator.next();
							
							if (overlay instanceof WayPointOverlay && ((WayPointOverlay) overlay).getIndex()== (wayPoint) ) {
								
								fromPoint = ((WayPointOverlay) overlay).getGeoPoint();
								wpFound = true;
								break;
							}
							
						}
						if (wpFound == false)
						{
							Dialog.buildAlertDialog(context, "Error !", "Way Point #" + wayPoint + " wasn't found.");
							return;
						}
					}
					
					GeoPoint destGeoPoint = Mathematics.createDestnationPoint(
							(double) fromPoint.getLatitudeE6() / 1000000,
							(double) fromPoint.getLongitudeE6() / 1000000,
							(double) distance / 1000,
							bearing + Math.round(LocationService.getDeclination(fromPoint)));
					
					mapView.getOverlays().add(new BearingOverlay(fromPoint, destGeoPoint, getNextBearingOverlayIndex(mapView)));
					
					mapView.invalidate();
					
					StateSaver.getInstance().marshalOverlays(mapView.getOverlays());
				}
			}, geoPoint);
			
			dialog.show();
			
		} catch (Exception e) {
			log.error(e, e);
		}
		
	}
	
	public static int getNextWayPointOverlayIndex(MapView mapView) {
		int maxIndex = 0;
		for (Overlay overlay : mapView.getOverlays()) {
			if (overlay instanceof WayPointOverlay) {
				int overlayIndex = ((WayPointOverlay)overlay).getIndex();
				if (overlayIndex > maxIndex) {
					maxIndex = overlayIndex;
				}
			}
		}
		return maxIndex+1;
	}
	public static int getNextBearingOverlayIndex(MapView mapView) {
		int maxIndex = 0;
		for (Overlay overlay : mapView.getOverlays()) {
			if (overlay instanceof BearingOverlay) {
				int overlayIndex = ((BearingOverlay)overlay).getIndex();
				if (overlayIndex > maxIndex) {
					maxIndex = overlayIndex;
				}
			}
		}
		return maxIndex+1;
	}
	
	
	public static Iterator<Overlay> searchBearingLine(Iterator<Overlay> iterator, int index) {
		
		
		while (iterator.hasNext()) {
			
			Overlay overlay = (Overlay) iterator.next();
			
			if (overlay instanceof BearingOverlay && (((BearingOverlay) overlay).getIndex()==index || index == 0)) {
				
				return iterator;
			}
		}
		return null;
	}
	
	public static void cleanBearingLine(final MapView mapView, Context context, int overlayIndex) {
	
		Iterator<Overlay> iterator;
		iterator = searchBearingLine(mapView.getOverlays().iterator(), overlayIndex);
		if (iterator != null)
		{
			iterator.remove();
			mapView.invalidate();
		}
	}
	
	
	public static Iterator<Overlay> searchWayPoint(Iterator<Overlay> iterator, int index) {
		
		while (iterator.hasNext()) {
			
			Overlay overlay = (Overlay) iterator.next();
			
			if (overlay instanceof WayPointOverlay && (((WayPointOverlay) overlay).getIndex()==index || index == 0)) { 
				
				return iterator;
			}
		}
		return null;
	}
	
	
	public static void cleanWaypoint(final MapView mapView, final Context context, int overlayIndex) {
		
		Iterator<Overlay> iterator;
		iterator = searchWayPoint(mapView.getOverlays().iterator(), overlayIndex);
		if (iterator != null)
		{
			iterator.remove();
			mapView.invalidate();
		}
		
	}
	
	public static void cleanWalkingPath(final MapView mapView) {
		
		Iterator<Overlay> iterator = mapView.getOverlays().iterator();
		
		while (iterator.hasNext()) {
			
			Overlay overlay = (Overlay) iterator.next();
			
			if (overlay instanceof WalkingPathOverlay) {
				
				((WalkingPathOverlay) overlay).clean();
			}
			
		}
		
		mapView.invalidate();

	}
	
	public static void clean (final MapView mapView, final Context context) {
		
		CleanDialog dialog = new CleanDialog(context, mapView);
		
		dialog.setTitle("Clean map");
		dialog.show();
	}
	

	
	public static void addWayPoint(final MapView mapView, Context context, final LocationService locationService, 
			boolean longpress, GeoPoint geoPoint) {
			
		if (longpress == false) {
			if (locationService.getLastGeoPoint() == null) {
					
				Dialog.buildAlertDialog(context, "Error !", "Please wait for GPS signal first.");
				
				return;
			}
			
			mapView.getOverlays().add(new WayPointOverlay(locationService.getLastGeoPoint(), getNextWayPointOverlayIndex(mapView)));
		}
		else
			mapView.getOverlays().add(new WayPointOverlay(geoPoint, getNextWayPointOverlayIndex(mapView)));
	    
	    
	    mapView.invalidate();
	    
	    StateSaver.getInstance().marshalOverlays(mapView.getOverlays());
	}
	
	public static void settings(Context context) {
		
		SettingsDialog dialog = new SettingsDialog(context);
		dialog.setTitle("Settings");
		dialog.show();
	}
	
	public static void about(Context context) {
		
		String app_ver = "";
		AboutDialog dialog = new AboutDialog(context);
		try {
			app_ver = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName;
		} catch (NameNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		dialog.setTitle(context.getResources().getString(R.string.app_name) + " " + app_ver);
		dialog.show();
		
	}
	
	
	public static void longpress(Context context, MapView mapView, Point longpressPoint, GeoPoint geoPoint, Overlay closestOverlay) {
		
		LongpressDialog dialog = new LongpressDialog(context, mapView, longpressPoint, geoPoint, closestOverlay);
		
		dialog.show();
	}

	public static GeoPoint getAnimateTo(MapView mapView) {
		for (Overlay overlay : mapView.getOverlays()) {
			if (overlay instanceof WalkingPathOverlay) {
				GeoPoint point = ((MarshalOverlay) overlay).getAnimateTo();
				if (point != null) {
					mapView.getController().animateTo(point);
				}
			}
		}
		for (Overlay overlay : mapView.getOverlays()) {
			if (overlay instanceof BearingOverlay) {
				GeoPoint point = ((MarshalOverlay) overlay).getAnimateTo();
				if (point != null) {
					mapView.getController().animateTo(point);
				}
			}
		}
		for (Overlay overlay : mapView.getOverlays()) {
			if (overlay instanceof WayPointOverlay) {
				GeoPoint point = ((MarshalOverlay) overlay).getAnimateTo();
				if (point != null) {
					mapView.getController().animateTo(point);
				}
			}
		}
		return null;
	}

}
